package server.handler.groupHandler;

import com.alibaba.fastjson.JSONObject;
import common.EnvelopeMessage;
import common.messages.GroupChatMessage;
import server.dao.GroupDao;
import server.dao.MessageDao;
import server.handler.SimpleHandler;
import server.session.Session;
import server.session.SessionManager;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class GroupChatHandler implements SimpleHandler {


    private static final Path BASE_DIR = Paths.get("data/uploads/");
    private static final Map<String, OutputStream> streamMap = new ConcurrentHashMap<>();

    @Override
    public void handle(EnvelopeMessage msg, Session session) {
        JSONObject body = (JSONObject) msg.getBody();
        String type = body.containsKey("messageType") ? body.getString("messageType") : "text";
        GroupChatMessage chatMsg = JSONObject.toJavaObject(body, GroupChatMessage.class);

        if ("fileChunk".equals(type)) {
            String fileUUID = body.getString("fileUUID");
            String fileName = body.getString("fileName");
            int chunkIndex = body.getIntValue("chunkIndex");
            int totalChunks = body.getIntValue("totalChunks");
            String base64Data = body.getString("fileChunk");
            try {

                Path groupDir = BASE_DIR.resolve("group_" + chatMsg.getGroupId());
                Files.createDirectories(groupDir);
                Path targetFile = groupDir.resolve(fileName);


                OutputStream out = streamMap.computeIfAbsent(fileUUID, id -> {
                    try {
                        return new BufferedOutputStream(Files.newOutputStream(targetFile, StandardOpenOption.CREATE, StandardOpenOption.APPEND));
                    } catch (IOException e) {
                        e.printStackTrace();
                        return null;
                    }
                });

                if (out != null) {
                    byte[] chunkBytes = Base64.getDecoder().decode(base64Data);
                    out.write(chunkBytes);
                    out.flush();
                }
                if (chunkIndex == totalChunks - 1) {
                    OutputStream outToClose = streamMap.remove(fileUUID);
                    if (outToClose != null) outToClose.close();
                    String filePath = targetFile.toString();
                    body.put("messageType", "file");
                    body.put("message", filePath);
                    body.put("fileName", fileName);
                    chatMsg = JSONObject.toJavaObject(body, GroupChatMessage.class);
                    chatMsg.setMessage(filePath);
                    new MessageDao().saveGroupMessage(chatMsg);
                    System.out.printf("%s(%d) 在群 %s(%d) 发送文件: %s (存储路径: %s)%n", chatMsg.getSenderName(), chatMsg.getSenderId(), chatMsg.getGroupName(), chatMsg.getGroupId(), fileName, filePath);
                    forwardToGroupMembers(chatMsg, msg, session);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        System.out.printf("%s(%d) 在群 %s(%d) 发送消息: %s%n", chatMsg.getSenderName(), chatMsg.getSenderId(), chatMsg.getGroupName(), chatMsg.getGroupId(), chatMsg.getMessage());
        new MessageDao().saveGroupMessage(chatMsg);
        forwardToGroupMembers(chatMsg, msg, session);
    }


    private void forwardToGroupMembers(GroupChatMessage chatMsg, EnvelopeMessage originalMsg, Session senderSession) {
        List<Integer> members = new GroupDao().selectUsersInGroup(chatMsg.getGroupId());
        for (Integer userId : members) {
            // 排除自己
            if (userId.equals(senderSession.getClientId())) continue;

            Session toSession = SessionManager.getSession(userId);
            if (toSession != null) {
                toSession.send(JSONObject.toJSONString(originalMsg));
            }
        }
    }
}